/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* includes (local) ----------------------------------------------------------*/
#include "k_init.h"
#include "k_task.h"
#include "k_errno.h"
/* includes (standard library, system) ---------------------------------------*/
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <x_config.h>
#include <x_warn.h>
#include <x_module.h>
#include <x_it.h>

#include <a_if.h>

/* defines -------------------------------------------------------------------*/
/* typedefs ------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/
/* variables (extern) --------------------------------------------------------*/

extern char __section_start__(init_cpu)[];
extern char __section_start__(init_user)[];
extern char __section_end__(init_user)[];

/* variables (global) --------------------------------------------------------*/
/* variables (local) ---------------------------------------------------------*/
/* inlines -------------------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/

extern int main(void);

static void __walk_init_table(init_pfn *start, init_pfn *end)
{
    while (start != end) {
        if ((*start++)() != 0) {
            WARN("Kernel initialization fail, last routine is %p, errno = %p\n", *start, errno);
        }
    }
}

static void __usr_init(uintptr_t arg)
{
    (void)arg;

    __walk_init_table((init_pfn *)__section_start__(init_user),
                      (init_pfn *)__section_end__(init_user));
}

/**
 * kernel_init - kernel initialization routine
 *
 * return : 0 on success, negative value on error
 */
__noreturn void kernel_init(void)
{
    __walk_init_table((init_pfn *)__section_start__(init_cpu),
                      (init_pfn *)__section_start__(init_user));

    /* run user init routines in deferred task */

#ifdef CONFIG_DEFER
    static deferred_job_t job = DEFERRED_JOB_INIT(__usr_init, 0);
    deferred_job_sched(&job);
#else
    __usr_init(0);
#endif

    task_sched_start();

    /* should never be here */

    while (1) {
        it_lock();
    }
}

/**
 * main_init - main_init task initialization routine
 *
 * return: 0 on success, negative value on error
 */
static int main_init(void)
{
    task_id tid;

    tid = task_spawn("main", CONFIG_MAIN_TASK_PRIO, CONFIG_MAIN_TASK_OPTIONS,
                     CONFIG_MAIN_TASK_STACK_SIZE, (int (*)(uintptr_t))main, 0);

    WARN_ON(tid == NULL, return -1, "Fail to create user task <main>!");

    return 0;
}

MODULE_INIT(user, main_init);
